package com.tengju.user.application.sentiment;

import com.fasterxml.jackson.core.type.TypeReference;
import com.tengju.data.domain.shared.JsonUtil;
import com.tengju.user.application.sentiment.dto.AddSentimentRecordForm;
import com.tengju.user.application.sentiment.dto.DeleteSentimentForm;
import com.tengju.user.application.sentiment.dto.UpdateSentimentRecordForm;
import com.tengju.user.application.shared.ApplicationException;
import com.tengju.user.application.shared.ApplicationExceptionCode;
import com.tengju.user.domain.model.sentiment.Sentiment;
import com.tengju.user.domain.model.sentiment.SentimentId;
import com.tengju.user.domain.model.sentiment.SentimentRepository;
import com.tengju.user.domain.model.user.SsoUserId;
import com.tengju.user.domain.model.user.Staff;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.shared.FormComponent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SentimentManageService {

    private final SentimentRepository sentimentRepository;

    @Value("${user.sentiment.details.form}")
    String sentimentDetailsFormModelString;


    public Boolean addSentimentRecord(AddSentimentRecordForm form, Staff staff) {
        List<FormComponent> formComponentList = FormComponent.jsonToSetComponentData(
                JsonUtil.toJSONString(form.getSentimentContextListJson()),
                JsonUtil.toList(sentimentDetailsFormModelString, new TypeReference<>() {
                }));

        Sentiment sentiment = new Sentiment(formComponentList, new SsoUserId(staff.getStaffId().getValue()),
                staff.getName(), new UserIdCode(form.getServiceProviderId()), LocalDateTime.now());

        return sentimentRepository.addSentimentRecord(sentiment);
    }

    public Boolean deleteSentimentRecord(DeleteSentimentForm form, Staff staff) {
        SentimentId sentimentId = Optional.ofNullable(form.getSentimentId()).map(SentimentId::new).orElse(null);
        checkIdCode(staff, sentimentId);
        return sentimentRepository.deleteSentimentRecordById(sentimentId);
    }

    public Boolean updateSentimentRecord(UpdateSentimentRecordForm form, Staff staff) {
        SentimentId sentimentId = Optional.ofNullable(form.getSentimentId()).map(SentimentId::new).orElse(null);
        checkIdCode(staff, sentimentId);
        List<FormComponent> formComponentList = FormComponent.jsonToSetComponentData(
                JsonUtil.toJSONString(form.getSentimentContextListJson()),
                JsonUtil.toList(sentimentDetailsFormModelString, new TypeReference<>() {
                }));
        return sentimentRepository.updateSentimentRecord(sentimentId, JsonUtil.toJSONString(formComponentList),
                new SsoUserId(staff.getStaffId().getValue()),
                staff.getName());
    }

    private void checkIdCode(Staff staff, SentimentId sentimentId) {
        if (sentimentId == null || staff == null) {
            throw ApplicationException.error(ApplicationExceptionCode.USERINFO_NOT_EXIST);
        }
        Sentiment sentiment = sentimentRepository.getSentimentRecordById(sentimentId);
        if (sentiment == null) {
            throw ApplicationException.error(ApplicationExceptionCode.USERINFO_NOT_EXIST, sentimentId.getValue());
        }
        if (sentiment.getSsoUserId().getValue() != staff.getStaffId().getValue()) {
            throw ApplicationException.error(ApplicationExceptionCode.INSUFFICIENT_PERMISSIONS);
        }
    }


}
